using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using Cinemachine;
using UnityEngine;
using UnityEngine.InputSystem;
using DG.Tweening;
using Unity.VisualScripting;

namespace MyProject.Persona
{
    public class PlayerController : MonoBehaviour
    {
        [HideInInspector] public bool startJump;
        [HideInInspector]public float varJumpTimer;
        [Header("切换大跳时间")]
        [SerializeField]private float varJumpTimerCount;

        [Header("跳跃力")] 
        public float varJumpSpeed;
        [Header("重力倍率")]
        public float fallMultiplier;
        [Header("上升倍率")]
        public float lowJumpMultiplier;
        [HideInInspector] public int jumpCount;
        [HideInInspector]public bool pressButton;

        private float maxFall;
        
        [Header("移动相关")] public float speed;
        [Header("开启匀速下落")]
        public bool startConstantSpeed;
        [Header("下落速度")]
        public float fallSpeed;
        // public float jumpForce;
        [HideInInspector]public Rigidbody2D rb;
        public PlayerInput _playerInput;
        private Vector2 _moveDir;
        private bool _faceDir;
        [HideInInspector]public PhysicsCheck physicsCheck; //物理检测

        [Header("人格切换")] public Personas curPersona;
        public List<Personas> personas = new List<Personas>();

        public JumpCheck _jumpCheck { get; set; } //土狼跳跃

        //技能相关
        private bool _releaseSkill;
        private float _releaseSkillTime;

        [Header("跳跃预输入")] [SerializeField] public bool inputAdvance;
        [HideInInspector]public bool startAdvance; //开始预输入
        // public Vector2 _jumpHigh; //跳到的最高点
        [HideInInspector]public bool canInputAdvance;
        [HideInInspector]public bool canAdvanceJump;
        [SerializeField] private float advanceDis;

        //状态机
        private BaseState curState;
        private InitialState InitialState => new InitialState(Personas.Initial, this);
        // [Header("泡泡cd")] public float paopaoCd;
        [HideInInspector]public bool canReleasePaopao;
        [Header("泡泡跳跃")]
        public float paopaoJumpForce;

        [Header("泡泡重力倍率")] public float paopaoFallMultiplier;
        [Header("泡泡跳跃匀速下落速度")] public float paopaoFallSpeed;

        [SerializeField] private GameObject followCamera;
        
        //人格切换cd
        [Header("人格切换cd")]
        [SerializeField] private float switchPersonaTime;
        private float _switchPersonaTime;

        // [SerializeField] private ParticleSystem deadParticle;

        private void Awake()
        {
            _playerInput = new PlayerInput();
            rb = GetComponent<Rigidbody2D>();
            physicsCheck = GetComponent<PhysicsCheck>();
            
            _playerInput.Gameplay.SwitchPerson.started += SwitchPersona;
            _playerInput.Gameplay.ReleaseSkill.started += ReleaseSkill;
            personas.Add(Personas.Initial);
        }

        private IEnumerator Start()
        {
            // curPersona = Persona.Blue;
            this._jumpCheck = new JumpCheck(this, Constants.EnableJumpGrace);
            curState = InitialState;
            yield return null;
            curState.OnStart();
        }

        private void OnEnable()
        {
            //TODO:做完主菜单记得把这个关掉
            _playerInput.Enable();
        }

        private void OnDisable()
        {
            _playerInput.Disable();
        }

        private void Update()
        {
            _moveDir = _playerInput.Gameplay.Move.ReadValue<Vector2>();

            //jump
            {
                //土狼跳跃
                _jumpCheck.UpdateJumpCheck();

                //var jump
                {
                    if (varJumpTimer > 0)
                    {
                        varJumpTimer -= Time.deltaTime;
                    }
                }
            }
            
            //切换人格
            {
                if (_switchPersonaTime > 0)
                {
                    _switchPersonaTime -= Time.deltaTime;
                }

                // if (paopaoCd > 0)
                // {
                //     paopaoCd -= Time.deltaTime;
                // }
                else
                {
                    canReleasePaopao = true;
                }
            }
            
            curState.LogicUpdate();
        }

        private void FixedUpdate()
        {
            if(!SkillManger.instance.isDash)
                Move();
        }

        private void Move()
        {
            rb.velocity = new Vector2(speed * Time.deltaTime * _moveDir.x, rb.velocity.y);

            int faceDir = (int)transform.localScale.x;
            if (_moveDir.x < 0 )
                faceDir = -1;
            else if (_moveDir.x > 0 )
                faceDir = 1;

            transform.localScale = new Vector3(faceDir, 1, 1);
        }

        //按键方面详情
        public void Jump()
        {
            GameInput.jump.ConsumeBuffer();
            _jumpCheck.ResetTime();
            // varJumpSpeed = Constants.JumpSpeed;
            // varJumpTimer = Constants.VarJumpTime;
            varJumpTimer = varJumpTimerCount;
            // rb.velocity = new Vector2(rb.velocity.x, Math.Max(rb.velocity.y, varJumpSpeed));
            startAdvance = true;
            // rb.AddForce(smallJumpForce * transform.up, ForceMode2D.Impulse);
        }

        //预输入
        public void AdvanceJump()
        {
            startAdvance = false;
            if (rb.velocity.y < 0)
            {
                if (Physics2D.Raycast(transform.position, Vector2.down, advanceDis, physicsCheck.groundLayer))
                {
                    canInputAdvance = true; 
                }
            }
        }
        
        private void SwitchPersona(InputAction.CallbackContext obj)
        {
            int transformDis = 100;
            if (!SkillManger.Instance.isReleaseSkill)
            {
                if (_switchPersonaTime <= 0)
                {
                    _switchPersonaTime = switchPersonaTime;
                    int index = (int)curPersona;
                    index++;
                    if (index >= personas.Count)
                    {
                        int i = index - 1;
                        transform.position = new Vector3(transform.position.x, transform.position.y + transformDis * i,
                            transform.position.z);
                        followCamera.transform.position = new Vector3(followCamera.transform.position.x,
                            followCamera.transform.position.y + transformDis * i, followCamera.transform.position.z);
                    }
                    else
                    {
                        transform.position = new Vector3(transform.position.x, transform.position.y - transformDis,
                            transform.position.z);
                        followCamera.transform.position = new Vector3(followCamera.transform.position.x,
                            followCamera.transform.position.y - transformDis , followCamera.transform.position.z);
                    }
                    
                    curPersona = personas[index % personas.Count];
                    Debug.Log(index);
                    
                }
            }
            
            
        }
        
        private void ReleaseSkill(InputAction.CallbackContext obj)
        {
            _releaseSkill = true;
            // StartCoroutine(SkillTimer(SkillManger.Instance.ReleaseSkill(curPersona)));
            SkillManger.Instance.ReleaseSkill(curPersona);
        }
        
        public float MaxFall
        {
            get => maxFall;
            set => maxFall = value;
        }

        private void OnTriggerStay2D(Collider2D other)
        {
            if (other.CompareTag("Can Dead"))
            {
                //TODO : 死亡事件
                // transform.DOScale(new Vector3(1.5f, 1.5f, 1), 1);
                Sprite sprite = GetComponent<SpriteRenderer>().sprite;
                GetComponent<SpriteRenderer>().DOColor(new Color(1, 1, 1, 0), 1);
                // deadParticle.Play();
                // GetComponent<CapsuleCollider2D>().enabled = false;
                _playerInput.Gameplay.Disable();
            }
        }
    }
}